package com.xy.xyaicpzs.util;

import com.xy.xyaicpzs.domain.entity.History100;
import com.xy.xyaicpzs.domain.entity.HistoryAll;
import com.xy.xyaicpzs.domain.entity.HistoryTop;
import com.xy.xyaicpzs.domain.entity.HistoryTop100;
import com.xy.xyaicpzs.domain.entity.BlueHistory100;
import com.xy.xyaicpzs.domain.entity.BlueHistoryAll;
import com.xy.xyaicpzs.domain.entity.BlueHistoryTop;
import com.xy.xyaicpzs.domain.entity.BlueHistoryTop100;
import com.xy.xyaicpzs.domain.entity.T3;
import com.xy.xyaicpzs.domain.entity.T4;
import com.xy.xyaicpzs.domain.entity.T5;
import com.xy.xyaicpzs.domain.entity.T6;
import com.xy.xyaicpzs.domain.entity.T7;
import com.xy.xyaicpzs.domain.entity.T8;
import com.xy.xyaicpzs.domain.entity.T11;
import com.xy.xyaicpzs.domain.entity.LotteryDraws;
import com.xy.xyaicpzs.mapper.History100Mapper;
import com.xy.xyaicpzs.mapper.HistoryAllMapper;
import com.xy.xyaicpzs.mapper.HistoryTop100Mapper;
import com.xy.xyaicpzs.mapper.HistoryTopMapper;
import com.xy.xyaicpzs.mapper.BlueHistory100Mapper;
import com.xy.xyaicpzs.mapper.BlueHistoryAllMapper;
import com.xy.xyaicpzs.mapper.BlueHistoryTop100Mapper;
import com.xy.xyaicpzs.mapper.BlueHistoryTopMapper;
import com.xy.xyaicpzs.mapper.T3Mapper;
import com.xy.xyaicpzs.mapper.T4Mapper;
import com.xy.xyaicpzs.mapper.T5Mapper;
import com.xy.xyaicpzs.mapper.T6Mapper;
import com.xy.xyaicpzs.mapper.T7Mapper;
import com.xy.xyaicpzs.mapper.T8Mapper;
import com.xy.xyaicpzs.mapper.T11Mapper;
import com.xy.xyaicpzs.mapper.LotteryDrawsMapper;
import com.xy.xyaicpzs.service.T3Service;
import com.xy.xyaicpzs.service.T4Service;
import com.xy.xyaicpzs.service.T5Service;
import com.xy.xyaicpzs.service.T6Service;
import com.xy.xyaicpzs.service.T7Service;
import com.xy.xyaicpzs.service.T8Service;
import com.xy.xyaicpzs.service.T11Service;
import com.xy.xyaicpzs.service.LotteryDrawsService;
import com.xy.xyaicpzs.service.HistoryAllService;
import com.xy.xyaicpzs.service.History100Service;
import com.xy.xyaicpzs.service.HistoryTopService;
import com.xy.xyaicpzs.service.HistoryTop100Service;
import com.xy.xyaicpzs.service.BlueHistoryAllService;
import com.xy.xyaicpzs.service.BlueHistory100Service;
import com.xy.xyaicpzs.service.BlueHistoryTopService;
import com.xy.xyaicpzs.service.BlueHistoryTop100Service;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * Excel数据导入工具类
 * 用于读取T1 sheet的数据并插入到四个数据库表中
 */
@Slf4j
@Component
public class ExcelDataImporter {

    @Autowired
    private HistoryAllMapper historyAllMapper;

    @Autowired
    private History100Mapper history100Mapper;

    @Autowired
    private HistoryTopMapper historyTopMapper;

    @Autowired
    private HistoryTop100Mapper historyTop100Mapper;

    @Autowired
    private BlueHistoryAllMapper blueHistoryAllMapper;

    @Autowired
    private BlueHistory100Mapper blueHistory100Mapper;

    @Autowired
    private BlueHistoryTopMapper blueHistoryTopMapper;

    @Autowired
    private BlueHistoryTop100Mapper blueHistoryTop100Mapper;

    @Autowired
    private T3Mapper t3Mapper;

    @Autowired
    private T4Mapper t4Mapper;

    @Autowired
    private T5Mapper t5Mapper;

    @Autowired
    private T6Mapper t6Mapper;

    @Autowired
    private T7Mapper t7Mapper;

    @Autowired
    private T8Mapper t8Mapper;

    @Autowired
    private T11Mapper t11Mapper;

    @Autowired
    private LotteryDrawsMapper lotteryDrawsMapper;

    @Autowired
    private T3Service t3Service;

    @Autowired
    private T4Service t4Service;

    @Autowired
    private T5Service t5Service;

    @Autowired
    private T6Service t6Service;

    @Autowired
    private T7Service t7Service;

    @Autowired
    private T8Service t8Service;

    @Autowired
    private T11Service t11Service;

    @Autowired
    private LotteryDrawsService lotteryDrawsService;

    @Autowired
    private HistoryAllService historyAllService;

    @Autowired
    private History100Service history100Service;

    @Autowired
    private HistoryTopService historyTopService;

    @Autowired
    private HistoryTop100Service historyTop100Service;

    @Autowired
    private BlueHistoryAllService blueHistoryAllService;

    @Autowired
    private BlueHistory100Service blueHistory100Service;

    @Autowired
    private BlueHistoryTopService blueHistoryTopService;

    @Autowired
    private BlueHistoryTop100Service blueHistoryTop100Service;

    /**
     * 导入Excel数据到数据库
     * @param filePath Excel文件路径
     */
    public void importExcelData(String filePath) {
        try (FileInputStream fis = new FileInputStream(filePath);
             XSSFWorkbook workbook = new XSSFWorkbook(fis)) {
            
            // 清空现有数据
            clearExistingData();

            // 处理T1 sheet（红球数据）
            Sheet t1Sheet = workbook.getSheet("T1");
            if (t1Sheet != null) {
                int lastRowNum = t1Sheet.getLastRowNum();
                log.info("开始导入T1数据（红球），共{}行", lastRowNum);

                // 读取数据并插入到各个表
                importHistoryAllData(t1Sheet, lastRowNum);
                importHistory100Data(t1Sheet, lastRowNum);
                importHistoryTopData(t1Sheet, lastRowNum);
                importHistoryTop100Data(t1Sheet, lastRowNum);

                log.info("T1数据（红球）导入完成");
            } else {
                log.warn("未找到T1工作表");
            }

            // 处理T2 sheet（蓝球数据）
            Sheet t2Sheet = workbook.getSheet("T2");
            if (t2Sheet != null) {
                int lastRowNum = t2Sheet.getLastRowNum();
                log.info("开始导入T2数据（蓝球），共{}行", lastRowNum);

                // 读取数据并插入到蓝球相关表
                importBlueHistoryAllData(t2Sheet, lastRowNum);
                importBlueHistory100Data(t2Sheet, lastRowNum);
                importBlueHistoryTopData(t2Sheet, lastRowNum);
                importBlueHistoryTop100Data(t2Sheet, lastRowNum);

                log.info("T2数据（蓝球）导入完成");
            } else {
                log.warn("未找到T2工作表");
            }

            // 处理T3 sheet（红球线系数数据）
            Sheet t3Sheet = workbook.getSheet("T3");
            if (t3Sheet != null) {
                log.info("开始导入T3数据（红球线系数）");
                List<T3> dataList = readT3DataFromSheet(t3Sheet);
                if (!dataList.isEmpty()) {
                    // 批量插入
                    t3Service.saveBatch(dataList);
                    log.info("成功导入{}条T3数据（红球线系数）", dataList.size());
                } else {
                    log.warn("未找到有效的T3数据");
                }
                log.info("T3数据（红球线系数）导入完成");
            } else {
                log.warn("未找到T3工作表");
            }

            // 处理T4 sheet（蓝球组红球线系数数据）
            Sheet t4Sheet = workbook.getSheet("T4");
            if (t4Sheet != null) {
                log.info("开始导入T4数据（蓝球组红球线系数）");
                List<T4> t4DataList = readT4DataFromSheet(t4Sheet);
                if (!t4DataList.isEmpty()) {
                    // 批量插入
                    t4Service.saveBatch(t4DataList);
                    log.info("成功导入{}条T4数据（蓝球组红球线系数）", t4DataList.size());
                } else {
                    log.warn("未找到有效的T4数据");
                }
                log.info("T4数据（蓝球组红球线系数）导入完成");
            } else {
                log.warn("未找到T4工作表");
            }

            // 处理T5 sheet（蓝球组蓝球线系数数据）
            Sheet t5Sheet = workbook.getSheet("T5");
            if (t5Sheet != null) {
                log.info("开始导入T5数据（蓝球组蓝球的线系数）");
                List<T5> t5DataList = readT5DataFromSheet(t5Sheet);
                if (!t5DataList.isEmpty()) {
                    // 批量插入
                    t5Service.saveBatch(t5DataList);
                    log.info("成功导入{}条T5数据（蓝球组蓝球的线系数）", t5DataList.size());
                } else {
                    log.warn("未找到有效的T5数据");
                }
                log.info("T5数据（蓝球组蓝球的线系数）导入完成");
            } else {
                log.warn("未找到T5工作表");
            }

            // 处理T6 sheet（红球组蓝球线系数数据）
            Sheet t6Sheet = workbook.getSheet("T6");
            if (t6Sheet != null) {
                log.info("开始导入T6数据（红球组蓝球线系数）");
                List<T6> t6DataList = readT6DataFromSheet(t6Sheet);
                if (!t6DataList.isEmpty()) {
                    // 批量插入
                    t6Service.saveBatch(t6DataList);
                    log.info("成功导入{}条T6数据（红球组蓝球线系数）", t6DataList.size());
                } else {
                    log.warn("未找到有效的T6数据");
                }
                log.info("T6数据（红球组蓝球线系数）导入完成");
            } else {
                log.warn("未找到T6工作表");
            }

            // 处理T7 sheet（红球组红球面系数数据）
            Sheet t7Sheet = workbook.getSheet("T7");
            if (t7Sheet != null) {
                log.info("开始导入T7数据（红球组红球面系数）");

                // 读取T7数据并插入到t7表
                importT7Data(t7Sheet);

                log.info("T7数据（红球组红球面系数）导入完成");
            } else {
                log.warn("未找到T7工作表");
            }

            // 处理T8 sheet（红球组蓝球面系数数据）
            Sheet t8Sheet = workbook.getSheet("T8");
            if (t8Sheet != null) {
                log.info("开始导入T8数据（红球组蓝球面系数）");
                List<T8> t8DataList = readT8DataFromSheet(t8Sheet);
                if (!t8DataList.isEmpty()) {
                    t8Service.saveBatch(t8DataList);
                    log.info("成功导入{}条T8数据（红球组蓝球面系数）", t8DataList.size());
                } else {
                    log.warn("未找到有效的T8数据");
                }
                log.info("T8数据（红球组蓝球面系数）导入完成");
            } else {
                log.warn("未找到T8工作表");
            }

//            // 处理T10 sheet（彩票开奖信息数据）
//            Sheet t10Sheet = workbook.getSheet("T10");
//            if (t10Sheet != null) {
//                log.info("开始导入T10数据（彩票开奖信息）");
//
//                // 读取T10数据并插入到lottery_draws表
//                importT10Data(t10Sheet);
//
//                log.info("T10数据（彩票开奖信息）导入完成");
//            } else {
//                log.warn("未找到T10工作表");
//            }

            // 处理T11 sheet（蓝球组红球面系数数据）
            Sheet t11Sheet = workbook.getSheet("T11");
            if (t11Sheet != null) {
                log.info("开始导入T11数据（蓝球组红球面系数）");
                List<T11> t11DataList = readT11DataFromSheet(t11Sheet);
                if (!t11DataList.isEmpty()) {
                    t11Service.saveBatch(t11DataList);
                    log.info("成功导入{}条T11数据（蓝球组红球面系数）", t11DataList.size());
                } else {
                    log.warn("未找到有效的T11数据");
                }
                log.info("T11数据（蓝球组红球面系数）导入完成");
            } else {
                log.warn("未找到T11工作表");
            }

            log.info("数据导入完成");

        } catch (IOException e) {
            log.error("读取Excel文件失败：{}", e.getMessage(), e);
            throw new RuntimeException("Excel文件读取失败", e);
        }
    }

    /**
     * 导入Excel的开奖数据到数据库
     * @param filePath Excel文件路径
     */
    public void importLotteryDrawsData(String filePath) {
        try (FileInputStream fis = new FileInputStream(filePath);
             XSSFWorkbook workbook = new XSSFWorkbook(fis)) {
            // 清空现有数据
            clearLotteryDrawsData();

            // 处理T10 sheet（彩票开奖信息数据）
            Sheet t10Sheet = workbook.getSheet("T10");
            if (t10Sheet != null) {
                log.info("开始导入T10数据（彩票开奖信息）");

                // 读取T10数据并插入到lottery_draws表
                importT10Data(t10Sheet);

                log.info("T10数据（彩票开奖信息）导入完成");
            } else {
                log.warn("未找到T10工作表");
            }

            log.info("数据导入完成");
        } catch (IOException e) {
            log.error("读取Excel文件失败：{}", e.getMessage(), e);
            throw new RuntimeException("Excel文件读取失败", e);
        }
    }

    /**
     * 追加导入Excel的开奖数据到数据库（不清空现有数据）
     * @param filePath Excel文件路径
     */
    public void appendLotteryDrawsData(String filePath) {
        try (FileInputStream fis = new FileInputStream(filePath);
             XSSFWorkbook workbook = new XSSFWorkbook(fis)) {
            
            // 处理T10 sheet（彩票开奖信息数据）
            Sheet t10Sheet = workbook.getSheet("T10");
            if (t10Sheet != null) {
                log.info("开始追加导入T10数据（彩票开奖信息）");

                // 读取T10数据并追加到lottery_draws表
                appendT10Data(t10Sheet);

                log.info("T10数据（彩票开奖信息）追加导入完成");
            } else {
                log.warn("未找到T10工作表");
            }

            log.info("追加数据导入完成");
        } catch (IOException e) {
            log.error("读取Excel文件失败：{}", e.getMessage(), e);
            throw new RuntimeException("Excel文件读取失败", e);
        }
    }

    /**
     * 清空现有数据
     */
    private void clearExistingData() {
        log.info("清空现有数据...");
        // 使用MyBatis-Plus的delete方法清空表
        // 清空红球数据表
        historyAllMapper.delete(null);
        history100Mapper.delete(null);
        historyTopMapper.delete(null);
        historyTop100Mapper.delete(null);
        
        // 清空蓝球数据表
        blueHistoryAllMapper.delete(null);
        blueHistory100Mapper.delete(null);
        blueHistoryTopMapper.delete(null);
        blueHistoryTop100Mapper.delete(null);
        
        // 清空T3数据表
        t3Mapper.delete(null);
        
        // 清空T4数据表
        t4Mapper.delete(null);
        
        // 清空T5数据表
        t5Mapper.delete(null);
        
        // 清空T6数据表
        t6Mapper.delete(null);
        
        // 清空T7数据表
        t7Mapper.delete(null);
        
        // 清空T8数据表
        t8Mapper.delete(null);
        
        // 清空T10数据表
        lotteryDrawsMapper.delete(null);
        
        // 清空T11数据表
        t11Mapper.delete(null);
    }

    /**
     * 清空现有开奖数据
     */
    private void clearLotteryDrawsData() {
        log.info("清空现有开奖数据...");
        // 使用MyBatis-Plus的delete方法清空表
        // 清空T10数据表
        lotteryDrawsMapper.delete(null);
    }

    /**
     * 导入全部历史数据 (列A-G)
     */
    private void importHistoryAllData(Sheet sheet, int lastRowNum) {
        log.info("开始导入全部历史数据...");
        List<HistoryAll> dataList = new ArrayList<>();

        for (int i = 1; i <= lastRowNum; i++) { // 跳过标题行
            Row row = sheet.getRow(i);
            if (row == null) continue;

            HistoryAll entity = new HistoryAll();
            
            // 列A: 球号
            entity.setBallNumber(getCellIntegerValue(row.getCell(0)));
            
            // 列B: 出现频次
            entity.setFrequencyCount(getCellIntegerValue(row.getCell(1)));
            
            // 列C: 出现频率百分比
            entity.setFrequencyPercentage(getCellNumericValue(row.getCell(2)));
            
            // 列D: 平均隐现期
            entity.setAverageInterval(getCellNumericValue(row.getCell(3)));
            
            // 列E: 最长隐现期
            entity.setMaxHiddenInterval(getCellIntegerValue(row.getCell(4)));
            
            // 列F: 最多连出期
            entity.setMaxConsecutiveCount(getCellIntegerValue(row.getCell(5)));
            
            // 列G: 点系数
            entity.setPointCoefficient(getCellNumericValue(row.getCell(6)));

            if (entity.getBallNumber() != null) {
                dataList.add(entity);
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            historyAllService.saveBatch(dataList);
            log.info("成功导入{}条全部历史数据", dataList.size());
        }
    }

    /**
     * 导入最近100期数据 (列H-L)
     */
    private void importHistory100Data(Sheet sheet, int lastRowNum) {
        log.info("开始导入最近100期数据...");
        List<History100> dataList = new ArrayList<>();

        for (int i = 1; i <= lastRowNum; i++) { // 跳过标题行
            Row row = sheet.getRow(i);
            if (row == null) continue;

            History100 entity = new History100();
            
            // 使用第一列的球号
            entity.setBallNumber(getCellIntegerValue(row.getCell(0)));
            
            // 列H: 出现频次
            entity.setFrequencyCount(getCellIntegerValue(row.getCell(8)));
            
            // 列J: 平均隐现期
            entity.setAverageInterval(getCellNumericValue(row.getCell(9)));
            
            // 列K: 当前隐现期
            entity.setNowInterval(getCellIntegerValue(row.getCell(10)));
            
            // 列L: 最多连出期
            entity.setMaxConsecutiveCount(getCellIntegerValue(row.getCell(11)));
            
            // 列M: 点系数
            entity.setPointCoefficient(getCellNumericValue(row.getCell(12)));

            if (entity.getBallNumber() != null) {
                dataList.add(entity);
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            history100Service.saveBatch(dataList);
            log.info("成功导入{}条最近100期数据", dataList.size());
        }
    }

    /**
     * 导入历史数据排行 (列N-P)
     */
    private void importHistoryTopData(Sheet sheet, int lastRowNum) {
        log.info("开始导入历史数据排行...");
        List<HistoryTop> dataList = new ArrayList<>();

        for (int i = 1; i <= lastRowNum; i++) { // 跳过标题行
            Row row = sheet.getRow(i);
            if (row == null) continue;

            HistoryTop entity = new HistoryTop();
            
            // 列N: 排行
            entity.setNo(getCellIntegerValue(row.getCell(14)));
            
            // 列O: 球号
            entity.setBallNumber(getCellIntegerValue(row.getCell(15)));
            
            // 列P: 点系数
            entity.setPointCoefficient(getCellNumericValue(row.getCell(16)));

            if (entity.getBallNumber() != null && entity.getNo() != null) {
                dataList.add(entity);
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            historyTopService.saveBatch(dataList);
            log.info("成功导入{}条历史数据排行", dataList.size());
        }
    }

    /**
     * 导入100期数据排行 (列Q-S)
     */
    private void importHistoryTop100Data(Sheet sheet, int lastRowNum) {
        log.info("开始导入100期数据排行...");
        List<HistoryTop100> dataList = new ArrayList<>();

        for (int i = 1; i <= lastRowNum; i++) { // 跳过标题行
            Row row = sheet.getRow(i);
            if (row == null) continue;

            HistoryTop100 entity = new HistoryTop100();
            
            // 列Q: 排行
            entity.setNo(getCellIntegerValue(row.getCell(18)));
            
            // 列R: 球号
            entity.setBallNumber(getCellIntegerValue(row.getCell(19)));
            
            // 列S: 点系数
            entity.setPointCoefficient(getCellNumericValue(row.getCell(20)));

            if (entity.getBallNumber() != null && entity.getNo() != null) {
                dataList.add(entity);
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            historyTop100Service.saveBatch(dataList);
            log.info("成功导入{}条100期数据排行", dataList.size());
        }
    }

    /**
     * 获取单元格的数值（保留两位小数）
     */
    private Double getCellNumericValue(Cell cell) {
        if (cell == null) return null;
        
        try {
            double value = 0.0;
            switch (cell.getCellType()) {
                case NUMERIC:
                    value = cell.getNumericCellValue();
                    break;
                case STRING:
                    String strValue = cell.getStringCellValue().trim();
                    if (strValue.isEmpty()) {
                        return null;
                    }
                    try {
                        value = Double.parseDouble(strValue);
                    } catch (NumberFormatException e) {
                        log.warn("无法解析单元格数值：{}", strValue);
                        return null;
                    }
                    break;
                case FORMULA:
                    try {
                        value = cell.getNumericCellValue();
                    } catch (Exception e) {
                        log.warn("无法获取公式单元格的数值：{}", e.getMessage());
                        return null;
                    }
                    break;
                case BLANK:
                    return null;
                default:
                    log.warn("不支持的单元格类型：{}", cell.getCellType());
                    return null;
            }
            
            // 保留两位小数
            return roundToTwoDecimalPlaces(value);
            
        } catch (Exception e) {
            log.warn("读取单元格数据失败：{}", e.getMessage());
            return null;
        }
    }

    /**
     * 获取单元格的整数值
     */
    private Integer getCellIntegerValue(Cell cell) {
        Double numericValue = getCellNumericValue(cell);
        return numericValue != null ? numericValue.intValue() : null;
    }

    /**
     * 将数值保留两位小数
     * @param value 原始数值
     * @return 保留两位小数的数值
     */
    private Double roundToTwoDecimalPlaces(double value) {
        if (Double.isNaN(value) || Double.isInfinite(value)) {
            return null;
        }
        
        try {
            BigDecimal bd = new BigDecimal(Double.toString(value));
            return bd.setScale(2, RoundingMode.HALF_UP).doubleValue();
        } catch (Exception e) {
            log.warn("数值格式化失败：{}", value);
            return value;
        }
    }

    // ==================== 蓝球数据导入方法 ====================

    /**
     * 导入蓝球全部历史数据 (列A-G)
     */
    private void importBlueHistoryAllData(Sheet sheet, int lastRowNum) {
        log.info("开始导入蓝球全部历史数据...");
        List<BlueHistoryAll> dataList = new ArrayList<>();

        for (int i = 1; i <= lastRowNum; i++) { // 跳过标题行
            Row row = sheet.getRow(i);
            if (row == null) continue;

            BlueHistoryAll entity = new BlueHistoryAll();
            
            // 列A: 球号
            entity.setBallNumber(getCellIntegerValue(row.getCell(0)));
            
            // 列B: 出现频次
            entity.setFrequencyCount(getCellIntegerValue(row.getCell(1)));
            
            // 列C: 出现频率百分比
            entity.setFrequencyPercentage(getCellNumericValue(row.getCell(2)));
            
            // 列D: 平均隐现期
            entity.setAverageInterval(getCellNumericValue(row.getCell(3)));
            
            // 列E: 最长隐现期
            entity.setMaxHiddenInterval(getCellIntegerValue(row.getCell(4)));
            
            // 列F: 最多连出期
            entity.setMaxConsecutiveCount(getCellIntegerValue(row.getCell(5)));
            
            // 列G: 点系数
            entity.setPointCoefficient(getCellNumericValue(row.getCell(6)));

            if (entity.getBallNumber() != null) {
                dataList.add(entity);
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            blueHistoryAllService.saveBatch(dataList);
            log.info("成功导入{}条蓝球全部历史数据", dataList.size());
        }
    }

    /**
     * 导入蓝球最近100期数据 (列H-M)
     */
    private void importBlueHistory100Data(Sheet sheet, int lastRowNum) {
        log.info("开始导入蓝球最近100期数据...");
        List<BlueHistory100> dataList = new ArrayList<>();

        for (int i = 1; i <= lastRowNum; i++) { // 跳过标题行
            Row row = sheet.getRow(i);
            if (row == null) continue;

            BlueHistory100 entity = new BlueHistory100();
            
            // 使用第一列的球号
            entity.setBallNumber(getCellIntegerValue(row.getCell(0)));
            
            // 列H: 出现频次
            entity.setFrequencyCount(getCellIntegerValue(row.getCell(8)));
            
            // 列J: 平均隐现期
            entity.setAverageInterval(getCellNumericValue(row.getCell(9)));
            
            // 列K: 当前隐现期
            entity.setNowInterval(getCellIntegerValue(row.getCell(10)));
            
            // 列L: 最多连出期
            entity.setMaxConsecutiveCount(getCellIntegerValue(row.getCell(11)));
            
            // 列M: 点系数
            entity.setPointCoefficient(getCellNumericValue(row.getCell(12)));

            if (entity.getBallNumber() != null) {
                dataList.add(entity);
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            blueHistory100Service.saveBatch(dataList);
            log.info("成功导入{}条蓝球最近100期数据", dataList.size());
        }
    }

    /**
     * 导入蓝球历史数据排行 (列N-P)
     */
    private void importBlueHistoryTopData(Sheet sheet, int lastRowNum) {
        log.info("开始导入蓝球历史数据排行...");
        List<BlueHistoryTop> dataList = new ArrayList<>();

        for (int i = 1; i <= lastRowNum; i++) { // 跳过标题行
            Row row = sheet.getRow(i);
            if (row == null) continue;

            BlueHistoryTop entity = new BlueHistoryTop();
            
            // 列N: 排行
            entity.setNo(getCellIntegerValue(row.getCell(14)));
            
            // 列O: 球号
            entity.setBallNumber(getCellIntegerValue(row.getCell(15)));
            
            // 列P: 点系数
            entity.setPointCoefficient(getCellNumericValue(row.getCell(16)));

            if (entity.getBallNumber() != null && entity.getNo() != null) {
                dataList.add(entity);
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            blueHistoryTopService.saveBatch(dataList);
            log.info("成功导入{}条蓝球历史数据排行", dataList.size());
        }
    }

    /**
     * 导入蓝球100期数据排行 (列Q-S)
     */
    private void importBlueHistoryTop100Data(Sheet sheet, int lastRowNum) {
        log.info("开始导入蓝球100期数据排行...");
        List<BlueHistoryTop100> dataList = new ArrayList<>();

        for (int i = 1; i <= lastRowNum; i++) { // 跳过标题行
            Row row = sheet.getRow(i);
            if (row == null) continue;

            BlueHistoryTop100 entity = new BlueHistoryTop100();
            
            // 列Q: 排行
            entity.setNo(getCellIntegerValue(row.getCell(18)));
            
            // 列R: 球号
            entity.setBallNumber(getCellIntegerValue(row.getCell(19)));
            
            // 列S: 点系数
            entity.setPointCoefficient(getCellNumericValue(row.getCell(20)));

            if (entity.getBallNumber() != null && entity.getNo() != null) {
                dataList.add(entity);
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            blueHistoryTop100Service.saveBatch(dataList);
            log.info("成功导入{}条蓝球100期数据排行", dataList.size());
        }
    }

    // ==================== T3数据导入方法 ====================

    /**
     * 导入T3数据（红球线系数）
     * 数据结构：每三列为一组，每组有33行数据
     * 从球号固定为1-33（行号），线系数在C、F、I、L...列
     */
    private void importT3Data(Sheet sheet) {
        log.info("开始导入T3数据（红球线系数）...");
        List<T3> dataList = new ArrayList<>();

        // 获取数据行数，跳过标题行，应该有33行数据
        int lastRowNum = sheet.getLastRowNum();
        
        // 计算组数，每组占用3列，从A列开始
        int totalCols = 0;
        if (lastRowNum > 0) {
            Row firstDataRow = sheet.getRow(1);
            if (firstDataRow != null) {
                totalCols = firstDataRow.getLastCellNum();
            }
        }
        
        int groupCount = totalCols / 3; // 每组3列
        log.info("检测到{}组数据，共{}列，预期33行数据", groupCount, totalCols);

        // 遍历每组数据
        for (int group = 0; group < groupCount; group++) {
            int masterBallNumber = group + 1; // 主球号从1开始
            int lineCoefCol = group * 3 + 2; // 线系数列：2,5,8,11...（C,F,I,L列）
            
            log.info("处理第{}组数据（主球{}号），线系数列位置：{}", group + 1, masterBallNumber, lineCoefCol);

            // 遍历33行数据（跳过标题行）
            for (int i = 1; i <= lastRowNum && i <= 33; i++) {
                Row row = sheet.getRow(i);
                if (row == null) continue;

                T3 entity = new T3();
                entity.setMasterBallNumber(masterBallNumber);
                
                // 从球号固定为行号（1-33）
                Integer slaveBallNumber = i;
                
                // 线系数（从对应组的第二列读取）
                Double lineCoefficient = getCellNumericValue(row.getCell(lineCoefCol));

                if (lineCoefficient != null) {
                    entity.setSlaveBallNumber(slaveBallNumber);
                    entity.setLineCoefficient(lineCoefficient);
                    dataList.add(entity);
                } else {
                    log.warn("第{}组第{}行线系数为空，跳过", group + 1, i);
                }
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            t3Service.saveBatch(dataList);
            log.info("成功导入{}条T3数据（红球线系数）", dataList.size());
        } else {
            log.warn("未找到有效的T3数据");
        }
    }

    // ==================== T4数据读取方法 ====================

    public List<T4> readT4DataFromSheet(Sheet sheet) {
        log.info("开始读取T4数据（蓝球组红球的线系数）...");
        List<T4> dataList = new ArrayList<>();

        // 获取数据行数，跳过标题行，应该有33行数据
        int lastRowNum = sheet.getLastRowNum();

        // 计算组数，每组占用3列，从A列开始
        int totalCols = 0;
        if (lastRowNum > 0) {
            Row firstDataRow = sheet.getRow(1);
            if (firstDataRow != null) {
                totalCols = firstDataRow.getLastCellNum();
            }
        }

        int groupCount = totalCols / 3; // 每组3列
        // 蓝球号码范围是1-16，所以最多16组
        groupCount = Math.min(groupCount, 16);

        log.info("检测到{}组数据，共{}列，预期33行数据", groupCount, totalCols);

        // 遍历每组数据（蓝球1-16号）
        for (int group = 0; group < groupCount; group++) {
            int masterBallNumber = group + 1; // 蓝球号从1开始
            int slaveBallCol = group * 3 + 1; // 从球号列：B,E,H,...
            int lineCoefCol = group * 3 + 2; // 线系数列：C,F,I,...

            log.info("处理第{}组数据（蓝球{}号），从球号列：{}，线系数列位置：{}", group + 1, masterBallNumber, slaveBallCol, lineCoefCol);

            // 遍历33行数据（红球1-33号，跳过标题行）
            for (int i = 1; i <= lastRowNum && i <= 33; i++) {
                Row row = sheet.getRow(i);
                if (row == null) continue;

                T4 entity = new T4();
                entity.setMasterBallNumber(masterBallNumber); // 蓝球号

                // 从对应组的第一列读取从球号
                Double slaveBallDouble = getCellNumericValue(row.getCell(slaveBallCol));
                Integer slaveBallNumber = (slaveBallDouble != null) ? slaveBallDouble.intValue() : null;

                // 线系数（从对应组的第二列读取）
                Double lineCoefficient = getCellNumericValue(row.getCell(lineCoefCol));

                if (slaveBallNumber != null && lineCoefficient != null) {
                    entity.setSlaveBallNumber(slaveBallNumber);
                    entity.setLineCoefficient(roundToTwoDecimalPlaces(lineCoefficient));
                    dataList.add(entity);
                } else {
                    log.warn("第{}组第{}行从球号或线系数为空，跳过", group + 1, i);
                }
            }
        }
        return dataList;
    }

    // ==================== T5数据读取方法 ====================

    // ==================== T6数据读取方法 ====================

    // ==================== T7数据导入方法 ====================

    /**
     * 导入T7数据（红球组红球的面系数）
     * 数据结构：每三列为一组，每组有33行数据，但需要排除自己和自己组合的情况
     * 红球号码范围：1-33（主球和从球都是）
     * 面系数在C、F、I、L...列
     * 特殊处理：1号只能与2-33组合，2号只能与1,3-33组合，以此类推
     */
    private void importT7Data(Sheet sheet) {
        log.info("开始导入T7数据（红球组红球的面系数）...");
        List<T7> dataList = new ArrayList<>();

        // 获取数据行数，跳过标题行，应该有33行数据
        int lastRowNum = sheet.getLastRowNum();
        
        // 计算组数，每组占用3列，从A列开始
        int totalCols = 0;
        if (lastRowNum > 0) {
            Row firstDataRow = sheet.getRow(1);
            if (firstDataRow != null) {
                totalCols = firstDataRow.getLastCellNum();
            }
        }
        
        int groupCount = totalCols / 3; // 每组3列
        // 红球号码范围是1-33，所以最多33组
        groupCount = Math.min(groupCount, 33);
        
        log.info("检测到{}组数据，共{}列，数据行数{}，预期33行数据", groupCount, totalCols, lastRowNum);

        // 遍历每组数据（红球1-33号作为主球）
        for (int group = 0; group < groupCount; group++) {
            int masterBallNumber = group + 1; // 主红球号从1开始
            int ballNumberCol = group * 3 + 1; // 球号列：1,4,7,10...（B,E,H,K列）
            int faceCoefCol = group * 3 + 2; // 面系数列：2,5,8,11...（C,F,I,L列）
            
            log.info("处理第{}组数据（主红球{}号），球号列：{}，面系数列：{}", group + 1, masterBallNumber, ballNumberCol, faceCoefCol);

            int validDataCount = 0; // 统计这组有效数据数量
            int skippedDiagonal = 0; // 统计跳过的对角线数量
            int emptyBallNumber = 0; // 统计球号为空的数量
            int emptyCoefficient = 0; // 统计面系数为空的数量

            // 遍历所有数据行（跳过标题行）
            // 需要读取到最后一行数据，确保包含33号球
            for (int rowIndex = 1; rowIndex <= lastRowNum; rowIndex++) {
                Row row = sheet.getRow(rowIndex);
                if (row == null) {
                    continue;
                }

                // 从Excel中读取球号（从球号列读取）
                Integer slaveBallNumber = getCellIntegerValue(row.getCell(ballNumberCol));
                if (slaveBallNumber == null) {
                    emptyBallNumber++;
                    continue; // 如果球号为空，跳过这行
                }
                
                // 不排除对角线，读取到什么就插入什么
                // if (masterBallNumber == slaveBallNumber) {
                //     skippedDiagonal++;
                //     log.debug("跳过对角线组合：主球{}，从球{}", masterBallNumber, slaveBallNumber);
                //     continue;
                // }

                // 面系数（从对应组的面系数列读取）
                Double faceCoefficient = getCellNumericValue(row.getCell(faceCoefCol));

                if (faceCoefficient != null) {
                    T7 entity = new T7();
                    entity.setMasterBallNumber(masterBallNumber); // 主红球号
                    entity.setSlaveBallNumber(slaveBallNumber);   // 从红球号
                    entity.setFaceCoefficient(roundToTwoDecimalPlaces(faceCoefficient));
                    dataList.add(entity);
                    validDataCount++;
                    
                    // 特别记录1号组33号球的数据
                    if (masterBallNumber == 1 && slaveBallNumber == 33) {
                        log.info("★ 重要数据：主球1，从球33，Excel行{}，面系数{}", rowIndex + 1, faceCoefficient);
                    }
                    
                    log.debug("添加T7数据：主球{}，从球{}，Excel行{}，面系数{}", 
                        masterBallNumber, slaveBallNumber, rowIndex + 1, faceCoefficient);
                } else {
                    emptyCoefficient++;
                    log.debug("第{}组第{}行面系数为空，球号{}，跳过", group + 1, rowIndex + 1, slaveBallNumber);
                }
            }
            
            // 统计这组的处理结果
            log.info("第{}组统计：有效数据{}条，跳过对角线{}条，球号为空{}条，面系数为空{}条", 
                group + 1, validDataCount, skippedDiagonal, emptyBallNumber, emptyCoefficient);
            
            if (validDataCount != 33) {
                log.warn("第{}组数据异常：应该有33条有效数据，实际{}条", group + 1, validDataCount);
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            t7Service.saveBatch(dataList);
            log.info("成功导入{}条T7数据（红球组红球的面系数）", dataList.size());
            log.info("预期数据量：33个红球 × 32个红球（排除自己） = 1056条记录");
            
            // 验证关键数据点
            boolean found1_33 = dataList.stream().anyMatch(t7 -> 
                t7.getMasterBallNumber() == 1 && t7.getSlaveBallNumber() == 33);
            if (found1_33) {
                T7 record1_33 = dataList.stream()
                    .filter(t7 -> t7.getMasterBallNumber() == 1 && t7.getSlaveBallNumber() == 33)
                    .findFirst().orElse(null);
                log.info("验证成功：找到(1,33)记录，面系数={}", record1_33.getFaceCoefficient());
            } else {
                log.warn("验证失败：未找到(1,33)记录");
            }
            
            // 统计每组的记录数（应该都是32条，排除对角线）
            for (int master = 1; master <= Math.min(groupCount, 5); master++) {
                final int masterNum = master;
                long count = dataList.stream().filter(t7 -> t7.getMasterBallNumber() == masterNum).count();
                log.info("主球{}号记录数：{}（应该是32）", masterNum, count);
            }
            
            // 验证对角线数据不存在
            long diagonalCount = dataList.stream()
                .filter(t7 -> t7.getMasterBallNumber().equals(t7.getSlaveBallNumber()))
                .count();
            log.info("对角线记录数：{}（应该是0）", diagonalCount);
            
            // 验证从球号范围
            Set<Integer> slaveBallNumbers = dataList.stream()
                .map(T7::getSlaveBallNumber)
                .collect(java.util.stream.Collectors.toSet());
            log.info("从球号范围：{}到{}，总数：{}（应该是1到33）", 
                slaveBallNumbers.stream().min(Integer::compareTo).orElse(0),
                slaveBallNumbers.stream().max(Integer::compareTo).orElse(0),
                slaveBallNumbers.size());
            
            // 验证是否包含33号球
            boolean has33 = slaveBallNumbers.contains(33);
            log.info("是否包含33号球：{}（应该是true）", has33);
            
            // 详细分析缺失的球号
            List<Integer> missingSlaves = new ArrayList<>();
            for (int i = 1; i <= 33; i++) {
                if (!slaveBallNumbers.contains(i)) {
                    missingSlaves.add(i);
                }
            }
            if (!missingSlaves.isEmpty()) {
                log.warn("缺失的从球号：{}", missingSlaves);
            }
            
            // 统计每个主球的记录数，找出缺失的组合
            for (int master = 1; master <= 33; master++) {
                final int masterNum = master;
                long count = dataList.stream().filter(t7 -> t7.getMasterBallNumber() == masterNum).count();
                if (count != 33) {
                    log.warn("主球{}号记录数异常：{}（应该是33）", masterNum, count);
                    
                    // 找出这个主球缺失的从球号
                    Set<Integer> existingSlaves = dataList.stream()
                        .filter(t7 -> t7.getMasterBallNumber() == masterNum)
                        .map(T7::getSlaveBallNumber)
                        .collect(java.util.stream.Collectors.toSet());
                    
                    List<Integer> missingForThisMaster = new ArrayList<>();
                    for (int slave = 1; slave <= 33; slave++) {
                        if (!existingSlaves.contains(slave)) {
                            missingForThisMaster.add(slave);
                        }
                    }
                    if (!missingForThisMaster.isEmpty()) {
                        log.warn("主球{}号缺失的从球号：{}", masterNum, missingForThisMaster);
                    }
                }
            }
            
            // 验证总记录数
            log.info("实际记录数：{}，预期记录数：{}（33×33=1089），差异：{}", 
                dataList.size(), 33 * 33, (33 * 33) - dataList.size());
        } else {
            log.warn("未找到有效的T7数据");
        }
    }

    // ==================== T8数据读取方法 ====================

    // ==================== T11数据读取方法 ====================

    // ==================== T10数据导入方法 ====================

    /**
     * 导入T10数据（彩票开奖信息）
     * 数据结构：标准表格结构
     * A列：开奖期号，B列：开奖日期
     * C-H列：红球1-6，I列：蓝球
     */
    private void importT10Data(Sheet sheet) {
        log.info("开始导入T10数据（彩票开奖信息）...");
        List<LotteryDraws> dataList = new ArrayList<>();

        // 获取数据行数，跳过标题行
        int lastRowNum = sheet.getLastRowNum();
        log.info("T10工作表共{}行数据（包含标题行）", lastRowNum + 1);

        for (int i = 1; i <= lastRowNum; i++) { // 跳过标题行
            Row row = sheet.getRow(i);
            if (row == null) continue;

            LotteryDraws entity = new LotteryDraws();
            
            // A列: 开奖期号
            Long drawId = getCellLongValue(row.getCell(0));
            if (drawId == null) {
                log.warn("第{}行开奖期号为空，跳过", i + 1);
                continue;
            }
            entity.setDrawId(drawId);
            
            // B列: 开奖日期
            Date drawDate = getCellDateValue(row.getCell(1));
            if (drawDate == null) {
                log.warn("第{}行开奖日期为空，跳过", i + 1);
                continue;
            }
            entity.setDrawDate(drawDate);
            
            // C列: 红球1
            entity.setRedBall1(getCellIntegerValue(row.getCell(2)));
            
            // D列: 红球2
            entity.setRedBall2(getCellIntegerValue(row.getCell(3)));
            
            // E列: 红球3
            entity.setRedBall3(getCellIntegerValue(row.getCell(4)));
            
            // F列: 红球4
            entity.setRedBall4(getCellIntegerValue(row.getCell(5)));
            
            // G列: 红球5
            entity.setRedBall5(getCellIntegerValue(row.getCell(6)));
            
            // H列: 红球6
            entity.setRedBall6(getCellIntegerValue(row.getCell(7)));
            
            // I列: 蓝球
            entity.setBlueBall(getCellIntegerValue(row.getCell(8)));

            // 验证必要字段
            if (entity.getRedBall1() != null && entity.getRedBall2() != null && 
                entity.getRedBall3() != null && entity.getRedBall4() != null && 
                entity.getRedBall5() != null && entity.getRedBall6() != null && 
                entity.getBlueBall() != null) {
                dataList.add(entity);
                log.debug("添加开奖记录：期号{}，日期{}，红球{}-{}-{}-{}-{}-{}，蓝球{}", 
                    entity.getDrawId(), entity.getDrawDate(),
                    entity.getRedBall1(), entity.getRedBall2(), entity.getRedBall3(),
                    entity.getRedBall4(), entity.getRedBall5(), entity.getRedBall6(),
                    entity.getBlueBall());
            } else {
                log.warn("第{}行数据不完整，跳过", i + 1);
            }
        }

        // 批量插入
        if (!dataList.isEmpty()) {
            lotteryDrawsService.saveBatch(dataList);
            log.info("成功导入{}条T10数据（彩票开奖信息）", dataList.size());
        } else {
            log.warn("未找到有效的T10数据");
        }
    }

    /**
     * 获取单元格的Long值
     */
    private Long getCellLongValue(Cell cell) {
        if (cell == null) return null;
        
        try {
            switch (cell.getCellType()) {
                case NUMERIC:
                    return (long) cell.getNumericCellValue();
                case STRING:
                    String strValue = cell.getStringCellValue().trim();
                    if (strValue.isEmpty()) return null;
                    return Long.parseLong(strValue);
                case FORMULA:
                    return (long) cell.getNumericCellValue();
                case BLANK:
                    return null;
                default:
                    log.warn("不支持的单元格类型：{}", cell.getCellType());
                    return null;
            }
        } catch (Exception e) {
            log.warn("读取Long值失败：{}", e.getMessage());
            return null;
        }
    }

    /**
     * 获取单元格的Date值
     */
    private Date getCellDateValue(Cell cell) {
        if (cell == null) return null;
        
        try {
            switch (cell.getCellType()) {
                case NUMERIC:
                    if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                        return cell.getDateCellValue();
                    } else {
                        // 如果是数字，尝试转换为日期
                        return org.apache.poi.ss.usermodel.DateUtil.getJavaDate(cell.getNumericCellValue());
                    }
                case STRING:
                    String strValue = cell.getStringCellValue().trim();
                    if (strValue.isEmpty()) return null;
                    // 尝试解析字符串日期，支持多种格式
                    return parseStringToDate(strValue);
                case FORMULA:
                    if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) {
                        return cell.getDateCellValue();
                    } else {
                        return org.apache.poi.ss.usermodel.DateUtil.getJavaDate(cell.getNumericCellValue());
                    }
                case BLANK:
                    return null;
                default:
                    log.warn("不支持的日期单元格类型：{}", cell.getCellType());
                    return null;
            }
        } catch (Exception e) {
            log.warn("读取Date值失败：{}", e.getMessage());
            return null;
        }
    }

    /**
     * 解析字符串为日期
     */
    private Date parseStringToDate(String dateStr) {
        try {
            // 支持多种日期格式
            java.text.SimpleDateFormat[] formats = {
                new java.text.SimpleDateFormat("yyyy-MM-dd"),
                new java.text.SimpleDateFormat("yyyy/MM/dd"),
                new java.text.SimpleDateFormat("yyyy-M-d"),
                new java.text.SimpleDateFormat("yyyy/M/d")
            };
            
            for (java.text.SimpleDateFormat format : formats) {
                try {
                    return format.parse(dateStr);
                } catch (java.text.ParseException ignored) {
                    // 继续尝试下一种格式
                }
            }
            
            log.warn("无法解析日期字符串：{}", dateStr);
            return null;
        } catch (Exception e) {
            log.warn("解析日期字符串失败：{}", e.getMessage());
            return null;
        }
    }

    /**
     * 追加导入T10数据（彩票开奖信息），检查重复数据
     * 数据结构：标准表格结构
     * A列：开奖期号，B列：开奖日期
     * C-H列：红球1-6，I列：蓝球
     */
    private void appendT10Data(Sheet sheet) {
        log.info("开始追加导入T10数据（彩票开奖信息）...");
        List<LotteryDraws> dataList = new ArrayList<>();
        int duplicateCount = 0;
        int newCount = 0;

        // 获取数据行数，跳过标题行
        int lastRowNum = sheet.getLastRowNum();
        log.info("T10工作表共{}行数据（包含标题行）", lastRowNum + 1);

        for (int i = 1; i <= lastRowNum; i++) { // 跳过标题行
            Row row = sheet.getRow(i);
            if (row == null) continue;

            LotteryDraws entity = new LotteryDraws();
            
            // A列: 开奖期号
            Long drawId = getCellLongValue(row.getCell(0));
            if (drawId == null) {
                log.warn("第{}行开奖期号为空，跳过", i + 1);
                continue;
            }
            entity.setDrawId(drawId);
            
            // 检查该期号是否已存在
            LotteryDraws existingRecord = lotteryDrawsMapper.selectById(drawId);
            if (existingRecord != null) {
                duplicateCount++;
                log.debug("开奖期号{}已存在，跳过", drawId);
                continue;
            }
            
            // B列: 开奖日期
            Date drawDate = getCellDateValue(row.getCell(1));
            if (drawDate == null) {
                log.warn("第{}行开奖日期为空，跳过", i + 1);
                continue;
            }
            entity.setDrawDate(drawDate);
            
            // C列: 红球1
            entity.setRedBall1(getCellIntegerValue(row.getCell(2)));
            
            // D列: 红球2
            entity.setRedBall2(getCellIntegerValue(row.getCell(3)));
            
            // E列: 红球3
            entity.setRedBall3(getCellIntegerValue(row.getCell(4)));
            
            // F列: 红球4
            entity.setRedBall4(getCellIntegerValue(row.getCell(5)));
            
            // G列: 红球5
            entity.setRedBall5(getCellIntegerValue(row.getCell(6)));
            
            // H列: 红球6
            entity.setRedBall6(getCellIntegerValue(row.getCell(7)));
            
            // I列: 蓝球
            entity.setBlueBall(getCellIntegerValue(row.getCell(8)));

            // 验证必要字段
            if (entity.getRedBall1() != null && entity.getRedBall2() != null && 
                entity.getRedBall3() != null && entity.getRedBall4() != null && 
                entity.getRedBall5() != null && entity.getRedBall6() != null && 
                entity.getBlueBall() != null) {
                dataList.add(entity);
                newCount++;
                log.debug("添加新开奖记录：期号{}，日期{}，红球{}-{}-{}-{}-{}-{}，蓝球{}", 
                    entity.getDrawId(), entity.getDrawDate(),
                    entity.getRedBall1(), entity.getRedBall2(), entity.getRedBall3(),
                    entity.getRedBall4(), entity.getRedBall5(), entity.getRedBall6(),
                    entity.getBlueBall());
            } else {
                log.warn("第{}行数据不完整，跳过", i + 1);
            }
        }

        // 批量插入新数据
        if (!dataList.isEmpty()) {
            lotteryDrawsService.saveBatch(dataList);
            log.info("成功追加导入{}条新的T10数据（彩票开奖信息）", dataList.size());
        } else {
            log.info("没有新的T10数据需要导入");
        }
        
        log.info("追加导入统计：新增{}条，跳过重复{}条", newCount, duplicateCount);
    }

    /**
     * 读取并保存T3表数据
     * @param filePath 文件路径
     * @throws IOException IO异常
     */
    public void readAndSaveT3Data(String filePath) throws IOException {
        log.info("开始读取并保存T3表数据，文件路径: {}", filePath);
        try (InputStream inputStream = new FileInputStream(filePath)) {
            readAndSaveT3Data(inputStream);
        }
    }

    public void readAndSaveT3Data(InputStream inputStream) throws IOException {
        log.info("开始读取并保存T3表数据...");
        List<T3> dataList;
        try (Workbook workbook = new XSSFWorkbook(inputStream)) {
            Sheet sheet = workbook.getSheet("T3");
            if (sheet == null) {
                log.warn("在提供的文件中未找到T3工作表");
                return;
            }
            dataList = readT3DataFromSheet(sheet);
        }

        if (!dataList.isEmpty()) {
            // 清空T3表
            t3Service.remove(null);
            log.info("已清空T3表");
            t3Service.saveBatch(dataList);
            log.info("成功保存 {} 条T3数据", dataList.size());
        } else {
            log.warn("没有读取到T3数据");
        }
    }

    private List<T3> readT3DataFromSheet(Sheet sheet) {
        List<T3> dataList = new ArrayList<>();

        int lastRowNum = sheet.getLastRowNum();
        int groupCount = 33; // T3表有33组数据

        // 遍历每组数据
        for (int group = 0; group < groupCount; group++) {
            int masterBallNumber = group + 1; // 主球号从1开始
            int slaveBallCol = group * 3 + 1; // 从球号列：1,4,7,10...（B,E,H,K列）
            int lineCoefCol = group * 3 + 2; // 线系数列：2,5,8,11...（C,F,I,L列）

            log.info("处理第{}组数据（主球{}号），从球号列: {}, 线系数列: {}", group + 1, masterBallNumber, slaveBallCol, lineCoefCol);

            // 遍历33行数据（跳过标题行）
            for (int i = 1; i <= lastRowNum && i <= 33; i++) {
                Row row = sheet.getRow(i);
                if (row == null) continue;

                T3 entity = new T3();
                entity.setMasterBallNumber(masterBallNumber);

                // 从对应组的第一列读取从球号
                Double slaveBallDouble = getCellNumericValue(row.getCell(slaveBallCol));
                Integer slaveBallNumber = (slaveBallDouble != null) ? slaveBallDouble.intValue() : null;

                // 线系数（从对应组的第二列读取）
                Double lineCoefficient = getCellNumericValue(row.getCell(lineCoefCol));

                if (slaveBallNumber != null && lineCoefficient != null) {
                    entity.setSlaveBallNumber(slaveBallNumber);
                    entity.setLineCoefficient(lineCoefficient);
                    dataList.add(entity);
                } else {
                    log.warn("第{}组第{}行从球号或线系数为空，跳过", group + 1, i);
                }
            }
        }
        return dataList;
    }

    /**
     * 从Sheet中读取T6数据（红球组蓝球的线系数）
     * @param sheet Excel工作表
     * @return T6数据列表
     */
    public List<T6> readT6DataFromSheet(Sheet sheet) {
        log.info("开始读取T6数据（红球组蓝球的线系数）...");
        List<T6> dataList = new ArrayList<>();

        // 获取数据行数，跳过标题行，应该有16行数据
        int lastRowNum = sheet.getLastRowNum();

        // 计算组数，每组占用3列，从A列开始
        int totalCols = 0;
        if (lastRowNum > 0) {
            Row firstDataRow = sheet.getRow(1);
            if (firstDataRow != null) {
                totalCols = firstDataRow.getLastCellNum();
            }
        }

        int groupCount = totalCols / 3; // 每组3列
        // 红球号码范围是1-33，所以最多33组
        groupCount = Math.min(groupCount, 33);

        log.info("检测到{}组数据，共{}列，预期16行数据", groupCount, totalCols);

        // 遍历每组数据（红球1-33号）
        for (int group = 0; group < groupCount; group++) {
            int masterBallNumber = group + 1; // 主红球号从1开始
            int slaveBallCol = group * 3 + 1; // 从球号列：B,E,H,...
            int lineCoefCol = group * 3 + 2; // 线系数列：C,F,I,...

            log.info("处理第{}组数据（主红球{}号），从球号列：{}，线系数列位置：{}", group + 1, masterBallNumber, slaveBallCol, lineCoefCol);

            // 遍历16行数据（从蓝球1-16号，跳过标题行）
            for (int i = 1; i <= lastRowNum && i <= 16; i++) {
                Row row = sheet.getRow(i);
                if (row == null) continue;

                T6 entity = new T6();
                entity.setMasterBallNumber(masterBallNumber); // 主红球号

                // 从对应组的第一列读取从球号
                Double slaveBallDouble = getCellNumericValue(row.getCell(slaveBallCol));
                Integer slaveBallNumber = (slaveBallDouble != null) ? slaveBallDouble.intValue() : null;

                // 线系数（从对应组的第二列读取）
                Double lineCoefficient = getCellNumericValue(row.getCell(lineCoefCol));

                if (slaveBallNumber != null && lineCoefficient != null) {
                    entity.setSlaveBallNumber(slaveBallNumber);
                    entity.setLineCoefficient(roundToTwoDecimalPlaces(lineCoefficient));
                    dataList.add(entity);
                } else {
                    log.warn("第{}组第{}行从球号或线系数为空，跳过", group + 1, i);
                }
            }
        }
        return dataList;
    }

    /**
     * 从Sheet中读取T8数据（红球组蓝球的面系数）
     * @param sheet Excel工作表
     * @return T8数据列表
     */
    public List<T8> readT8DataFromSheet(Sheet sheet) {
        log.info("开始读取T8数据（红球组蓝球的面系数）...");
        List<T8> dataList = new ArrayList<>();

        // 获取数据行数，跳过标题行，应该有16行数据
        int lastRowNum = sheet.getLastRowNum();

        // 计算组数，每组占用3列，从A列开始
        int totalCols = 0;
        if (lastRowNum > 0) {
            Row firstDataRow = sheet.getRow(1);
            if (firstDataRow != null) {
                totalCols = firstDataRow.getLastCellNum();
            }
        }

        int groupCount = totalCols / 3; // 每组3列
        // 红球号码范围是1-33，所以最多33组
        groupCount = Math.min(groupCount, 33);

        log.info("检测到{}组数据，共{}列，预期16行数据", groupCount, totalCols);

        // 遍历每组数据（红球1-33号）
        for (int group = 0; group < groupCount; group++) {
            int masterBallNumber = group + 1; // 主红球号从1开始
            int slaveBallCol = group * 3 + 1; // 从球号列：B,E,H,...
            int faceCoefCol = group * 3 + 2; // 面系数列：C,F,I,...

            log.info("处理第{}组数据（主红球{}号），从球号列：{}，面系数列位置：{}", group + 1, masterBallNumber, slaveBallCol, faceCoefCol);

            // 遍历16行数据（从蓝球1-16号，跳过标题行）
            for (int i = 1; i <= lastRowNum && i <= 16; i++) {
                Row row = sheet.getRow(i);
                if (row == null) continue;

                T8 entity = new T8();
                entity.setMasterBallNumber(masterBallNumber); // 主红球号

                // 从对应组的第一列读取从球号
                Double slaveBallDouble = getCellNumericValue(row.getCell(slaveBallCol));
                Integer slaveBallNumber = (slaveBallDouble != null) ? slaveBallDouble.intValue() : null;

                // 面系数（从对应组的第二列读取）
                Double faceCoefficient = getCellNumericValue(row.getCell(faceCoefCol));

                if (slaveBallNumber != null && faceCoefficient != null) {
                    entity.setSlaveBallNumber(slaveBallNumber);
                    entity.setFaceCoefficient(roundToTwoDecimalPlaces(faceCoefficient));
                    dataList.add(entity);
                } else {
                    log.warn("第{}组第{}行从球号或面系数为空，跳过", group + 1, i);
                }
            }
        }
        return dataList;
    }

    /**
     * 从Sheet中读取T11数据（蓝球组红球的面系数）
     * @param sheet Excel工作表
     * @return T11数据列表
     */
    public List<T11> readT11DataFromSheet(Sheet sheet) {
        log.info("开始读取T11数据（蓝球组红球的面系数）...");
        List<T11> dataList = new ArrayList<>();

        // 获取数据行数，跳过标题行，应该有33行数据
        int lastRowNum = sheet.getLastRowNum();

        // 计算组数，每组占用3列，从A列开始
        int totalCols = 0;
        if (lastRowNum > 0) {
            Row firstDataRow = sheet.getRow(1);
            if (firstDataRow != null) {
                totalCols = firstDataRow.getLastCellNum();
            }
        }

        int groupCount = totalCols / 3; // 每组3列
        // 蓝球号码范围是1-16，所以最多16组
        groupCount = Math.min(groupCount, 16);

        log.info("检测到{}组数据，共{}列，预期33行数据", groupCount, totalCols);

        // 遍历每组数据（蓝球1-16号）
        for (int group = 0; group < groupCount; group++) {
            int masterBallNumber = group + 1; // 蓝球号从1开始
            int slaveBallCol = group * 3 + 1; // 从球号列：B,E,H,...
            int faceCoefCol = group * 3 + 2; // 面系数列：C,F,I,...

            log.info("处理第{}组数据（蓝球{}号），从球号列：{}，面系数列位置：{}", group + 1, masterBallNumber, slaveBallCol, faceCoefCol);

            // 遍历33行数据（红球1-33号，跳过标题行）
            for (int i = 1; i <= lastRowNum && i <= 33; i++) {
                Row row = sheet.getRow(i);
                if (row == null) continue;

                T11 entity = new T11();
                entity.setMasterBallNumber(masterBallNumber); // 蓝球号

                // 从对应组的第一列读取从球号
                Double slaveBallDouble = getCellNumericValue(row.getCell(slaveBallCol));
                Integer slaveBallNumber = (slaveBallDouble != null) ? slaveBallDouble.intValue() : null;

                // 面系数（从对应组的第二列读取）
                Double faceCoefficient = getCellNumericValue(row.getCell(faceCoefCol));

                if (slaveBallNumber != null && faceCoefficient != null) {
                    entity.setSlaveBallNumber(slaveBallNumber);
                    entity.setFaceCoefficient(roundToTwoDecimalPlaces(faceCoefficient));
                    dataList.add(entity);
                } else {
                    log.warn("第{}组第{}行从球号或面系数为空，跳过", group + 1, i);
                }
            }
        }
        return dataList;
    }

    /**
     * 从Sheet中读取T5数据（蓝球组蓝球的线系数）
     * @param sheet Excel工作表
     * @return T5数据列表
     */
    public List<T5> readT5DataFromSheet(Sheet sheet) {
        log.info("开始读取T5数据（蓝球组蓝球的线系数）...");
        List<T5> dataList = new ArrayList<>();

        // 获取数据行数，跳过标题行，应该有16行数据
        int lastRowNum = sheet.getLastRowNum();

        // 计算组数，每组占用3列，从A列开始
        int totalCols = 0;
        if (lastRowNum > 0) {
            Row firstDataRow = sheet.getRow(1);
            if (firstDataRow != null) {
                totalCols = firstDataRow.getLastCellNum();
            }
        }

        int groupCount = totalCols / 3; // 每组3列
        // 蓝球号码范围是1-16，所以最多16组
        groupCount = Math.min(groupCount, 16);

        log.info("检测到{}组数据，共{}列，预期16行数据", groupCount, totalCols);

        // 遍历每组数据（蓝球1-16号）
        for (int group = 0; group < groupCount; group++) {
            int masterBallNumber = group + 1; // 主蓝球号从1开始
            int slaveBallCol = group * 3 + 1; // 从球号列：B,E,H,...
            int lineCoefCol = group * 3 + 2; // 线系数列：C,F,I,...

            log.info("处理第{}组数据（主蓝球{}号），从球号列：{}，线系数列位置：{}", group + 1, masterBallNumber, slaveBallCol, lineCoefCol);

            // 遍历16行数据（从蓝球1-16号，跳过标题行）
            for (int i = 1; i <= lastRowNum && i <= 16; i++) {
                Row row = sheet.getRow(i);
                if (row == null) continue;

                T5 entity = new T5();
                entity.setMasterBallNumber(masterBallNumber); // 主蓝球号

                // 从对应组的第一列读取从球号
                Double slaveBallDouble = getCellNumericValue(row.getCell(slaveBallCol));
                Integer slaveBallNumber = (slaveBallDouble != null) ? slaveBallDouble.intValue() : null;

                // 线系数（从对应组的第二列读取）
                Double lineCoefficient = getCellNumericValue(row.getCell(lineCoefCol));

                if (slaveBallNumber != null && lineCoefficient != null) {
                    entity.setSlaveBallNumber(slaveBallNumber);
                    entity.setLineCoefficient(roundToTwoDecimalPlaces(lineCoefficient));
                    dataList.add(entity);
                } else {
                    log.warn("第{}组第{}行从球号或线系数为空，跳过", group + 1, i);
                }
            }
        }
        return dataList;
    }
}